(* ocamlgsl - OCaml interface to GSL                        *)
(* Copyright (©) 2002-2012 - Olivier Andrieu                *)
(* distributed under the terms of the GPL version 3         *)

(** Fast Fourier Transforms *)

open Gsl_complex

exception Wrong_layout

type layout = 
  | Real 
  | Halfcomplex 
  | Halfcomplex_rad2
  | Complex

type fft_array = {
    mutable layout : layout ;
    data : float array }

module Real :
  sig
    type workspace
    type wavetable

    val make_workspace : int -> workspace
    val make_wavetable : int -> wavetable

    external transform :
      ?stride:int -> fft_array -> wavetable -> workspace -> unit
      = "ml_gsl_fft_real_transform"

    external transform_rad2 : 
      ?stride:int -> fft_array -> unit
      = "ml_gsl_fft_real_radix2_transform"

    val unpack : ?stride:int -> fft_array -> fft_array
  end

module Halfcomplex :
  sig
    type wavetable

    val make_wavetable : int -> wavetable

    external transform :
      ?stride:int -> fft_array -> wavetable -> Real.workspace -> unit
      = "ml_gsl_fft_halfcomplex_transform"

    external transform_rad2 : 
      ?stride:int -> fft_array -> unit
      = "ml_gsl_fft_halfcomplex_radix2_transform"

    external backward :
      ?stride:int -> fft_array -> wavetable -> Real.workspace -> unit
      = "ml_gsl_fft_halfcomplex_backward"

    external backward_rad2 : 
      ?stride:int -> fft_array -> unit
      = "ml_gsl_fft_halfcomplex_radix2_backward"

    external inverse :
      ?stride:int -> fft_array -> wavetable -> Real.workspace -> unit
      = "ml_gsl_fft_halfcomplex_inverse"

    external inverse_rad2 : 
      ?stride:int -> fft_array -> unit
      = "ml_gsl_fft_halfcomplex_radix2_inverse"

    val unpack : ?stride:int -> fft_array -> fft_array
  end

module Complex :
  sig
    type workspace
    type wavetable
    type direction = Forward | Backward

    val make_workspace : int -> workspace
    val make_wavetable : int -> wavetable

    external forward :
      ?stride:int -> complex_array -> wavetable -> workspace -> unit
      = "ml_gsl_fft_complex_forward"

    external forward_rad2 : 
      ?dif:bool -> ?stride:int -> complex_array -> unit
      = "ml_gsl_fft_complex_rad2_forward"

    external transform :
      ?stride:int -> complex_array -> wavetable -> workspace -> direction -> unit
      = "ml_gsl_fft_complex_transform"

    external transform_rad2 :
      ?dif:bool -> ?stride:int -> complex_array -> direction -> unit
      = "ml_gsl_fft_complex_rad2_transform"

    external backward :
      ?stride:int -> complex_array -> wavetable -> workspace -> unit
      = "ml_gsl_fft_complex_backward"

    external backward_rad2 : 
      ?dif:bool -> ?stride:int -> complex_array -> unit
      = "ml_gsl_fft_complex_rad2_backward"

    external inverse :
      ?stride:int -> complex_array -> wavetable -> workspace -> unit
      = "ml_gsl_fft_complex_inverse"

    external inverse_rad2 : 
      ?dif:bool -> ?stride:int -> complex_array -> unit
      = "ml_gsl_fft_complex_rad2_inverse"

  end

val unpack : fft_array -> complex_array

val hc_mult      : fft_array -> fft_array -> unit
val hc_mult_rad2 : fft_array -> fft_array -> unit
